#ifndef __laser
#define __laser
#include<vector>
#include "type.h"
#include "fields.h"
#include"simbox.h"
#include <iostream>

/// 产生一个激光，但需要实时更新
class __Laser{
    public:
        int is_able;
        /// 更新时间间隔dt
        double delta_t;
        /// type 0: 线偏振，1, 圆偏真
        int type;
        /// 空间dx dy
        __Vect2<double> xysize;
        /// 激光的id
        int id;
        /// 记录当前地多少个dt
        int t_now;
        /// 起始时间和脉冲时间宽度
        double t_center, duration;
        /// 脉冲电场振幅
        double amp;
        /// 激光频率
        double omega;
        /// 束腰宽度
        double waist;
        /// 生成的电场信息
        vector<__Vect3<double> > efields;
        /// 与电场信息对应的位置
        vector<__Vect2<int> > position;
        /// 当前场群的大小
        __Vect2<int> gridsize;
        /// 当前box的xymin
        __Vect2<double> xymin;
        /// 当前box的ximax
        __Vect2<double> xymax;
        /// 激光发射的中心位置
        __Vect2<double> pos;
        /// 中间变量，用于存储 激光横向延伸的网格
        int x;
        /// 偏振方向：
        int polarization;
        // position 与 efields 一一对应
        __Laser(){}
        __Laser(const int id, const int type, const double& dt, const double& t_center, \
                const double& duration_in_um, const\
                __Vect2<double> pos, const double& wavelength, const __Vect2<double>& xymin,\
                const __Vect2<double>& xymax, const __Vect2<int>& gridsize, const __Vect2<double>& xysize,  \
                const double& waist, const double& amplitude, const int& polarization)\
            :id(id), type(type), delta_t(dt), t_center(t_center), xymin(xymin), xymax(xymax)\
            , waist(waist), xysize(xysize), amp(amplitude), pos(pos), gridsize(gridsize), \
            polarization(polarization)
            {
                t_now = 0;
                x = int((pos.member[0] - xymin.member[0] + xysize.member[0]) / xysize.member[0]);
                if(polarization == 0)
                {
                    x = int((pos.member[1] - xymin.member[1] + xysize.member[1]) / xysize.member[1]);
                }
                duration = duration_in_um / c_light_speed;
                omega = 2.0 * PI * c_light_speed / wavelength;
                cout<<" omega = "<<omega<<endl;
                if(pos > xymin && pos < xymax)
                {
                    is_able = 1;
                }else
                {
                    is_able = 0;
                }
            }
        ~__Laser(){}
        /// 更新一步
        void update();
        /// 对mysimbox设置
        void setting_fields(__Simbox& mysimbox);
};

void __Laser::update()
{
    if(!is_able)
    {
        return;
    }
    double mytime = abs(delta_t * t_now - t_center);
    if(mytime > duration * 5.0)
    {
        return;
    }
    t_now ++;
    // 场和位置重新计算
    position.clear();
    efields.clear();
    // 只需要给定从那个边界出来，即给定一个x的坐标就可以
    // 在这里给出一个对应的formula来确定激光的形状
    // 我们假设一个y方向偏振高斯波包吧
    // ey = exp(-(x^2 + y^2) / 2 / l^2) * sin(wt)
    // j 的下界应该是1,但0处无值对于0进程，1进程可以交换的到。
    double length;
    for(int j = 0; j < gridsize.member[1]; j ++)
    {
        __Vect2<int> temppos(x, j);
        if(polarization == 0)
        {
            length = abs(pos.member[0] - xymin.member[0] - j * xysize.member[0]);
            temppos = __Vect2<int>(j, x);
        }
        else{
            length = abs(pos.member[1] - xymin.member[1] - j * xysize.member[1]);
        }
        position.push_back(temppos);
        __Vect3<double> tempefields(0, 0, 0);
        if(type == 0)
        {
            tempefields.member[polarization] = amp * exp(-(length * length) / waist / waist / 2.0) \
                                * exp(-(mytime * mytime) / (duration * duration) / 2.0)\
                                        * sin(omega * t_now * delta_t);
        
            efields.push_back(tempefields);
        }
        else if(type == 1)
        {
            tempefields.member[1] = amp * exp(-(length * length) / waist / waist / 2.0) \
                                * exp(-(mytime / duration) * ( mytime / duration) / 2.0)\
                                        * sin(omega * t_now * delta_t);
            tempefields.member[2] = amp * exp(-(length * length) / waist / waist / 2.0) \
                                * exp(-(mytime / duration) * ( mytime / duration) / 2.0)\
                                        * sin(omega * t_now * delta_t + PI * 0.5);
            efields.push_back(tempefields);
        }
    }
    
    
}

void __Laser::setting_fields(__Simbox& mysimbox)
{
    if(!is_able)
    {
        return;
    }
    double mytime = delta_t * t_now;
    if(mytime > 5.0 * duration)
    {
        return;
    }
    for(int i = 0; i < efields.size(); i ++)
    {
        if(position[i].member[0] < mysimbox.fieldgroup.member.size() && \
                position[i].member[0] >= 0 && \
                mysimbox.fieldgroup.member[0].size() > position[i].member[1] && \
                position[i].member[1] >= 0)
        {
            mysimbox.fieldgroup.member[position[i].member[0]]\
                [position[i].member[1]].efield = efields[i];
        }
    }
    efields.clear();
}

#endif
